﻿using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;
using winS.UnityEditor.Undo;

namespace winS.UnityEditor.UIElement
{
    /// <summary>
    /// <see cref="EditorElement"/> Factory.
    /// Provides creation of basic editor elements.
    /// </summary>
    public class ElementFactory
    {
        /// <summary>
        /// Right margin of Label.
        /// </summary>
        public virtual float labelMarginRight => EditorElementUtility.defaultLabelMarginRight;

        /// <summary>
        /// Vertical margin of <see cref="EditorControl"/>.
        /// </summary>
        public virtual float marginVertical => EditorElementUtility.defaultMarginVertical;
        /// <summary>
        /// Horizontal margin of <see cref="EditorControl"/>.
        /// </summary>
        public virtual float marginHorizontal => EditorElementUtility.defaultMarginHorizontal;

        /// <summary>
        /// Border color of element.
        /// </summary>
        public virtual Color borderColor => EditorElementUtility.defaultBorderColor;
        /// <summary>
        /// color of splitline.
        /// </summary>
        public virtual Color splitlineColor => EditorElementUtility.defaultSplitlineColor;
        /// <summary>
        /// White color (Soft).
        /// </summary>
        public virtual Color softWhiteColor => EditorElementUtility.defaultSoftWhiteColor;
        /// <summary>
        /// Color of element when highlight.
        /// </summary>
        public virtual Color highlightColor => EditorElementUtility.defaultHighlightColor;

        internal Length currentLabelWidth = -1f;

        protected readonly UndoSystem undoSystem;

        public ElementFactory()
        {
        }
        public ElementFactory(UndoSystem undoSystem)
        {
            this.undoSystem = undoSystem;
        }

        /// <summary>
        /// Set width of label.
        /// this value affect width of label in all <see cref="IEditorField"/>.
        /// </summary>
        public void SetLabelWidth(float width, LengthUnit lengthUnit = LengthUnit.Pixel) => currentLabelWidth = new Length(width, lengthUnit);
        /// <summary>
        /// Reset width of label.
        /// </summary>
        public void ResetLabelWidth() => currentLabelWidth = new Length(-1f);

        public virtual Table CreateTable()
        {
            return new Table();
        }
        public Table CreateTable(params KeyValuePair<string, float>[] headers)
        {
            Table table = CreateTable();
            table.SetHeaders(headers);
            return table;
        }

        public virtual HyperlinkText CreateHyperlinkText()
        {
            return new HyperlinkText();
        }
        public HyperlinkText CreateHyperlinkText(string text)
        {
            HyperlinkText hyperlinkText = CreateHyperlinkText();
            hyperlinkText.text = text;
            return hyperlinkText;
        }
        public HyperlinkText CreateHyperlinkText(Action onClickCallback)
        {
            HyperlinkText hyperlinkText = CreateHyperlinkText();
            hyperlinkText.onClick += onClickCallback;
            return hyperlinkText;
        }
        public HyperlinkText CreateHyperlinkText(string text, Action onClickCallback)
        {
            HyperlinkText hyperlinkText = CreateHyperlinkText(text);
            hyperlinkText.onClick += onClickCallback;
            return hyperlinkText;
        }

        public virtual EditorElement CreateEditorElement()
        {
            return new EditorElement(this);
        }
        public EditorElement CreateEditorElement(Color backgroundColor)
        {
            EditorElement visualElement = CreateEditorElement();
            visualElement.style.backgroundColor = backgroundColor;
            return visualElement;
        }
        public EditorElement CreateEditorElementWithName(string name)
        {
            EditorElement visualElement = CreateEditorElement();
            visualElement.name = name;
            return visualElement;
        }
        public EditorElement CreateEditorElementWithName(string name, Color backgroundColor)
        {
            EditorElement visualElement = CreateEditorElementWithName(name);
            visualElement.style.backgroundColor = backgroundColor;
            return visualElement;
        }

        public virtual Row CreateRow()
        {
            return new Row(this);
        }
        public Row CreateRow(float flexGrow)
        {
            Row row = CreateRow();
            row.style.flexGrow = flexGrow;
            return row;
        }
        public Row CreateRow(VisualElement child)
        {
            Row row = CreateRow();
            row.Add(child);
            return row;
        }
        public Row CreateRow(VisualElement child, float flexGrow)
        {
            Row row = CreateRow(flexGrow);
            row.Add(child);
            return row;
        }
        public Row CreateRow(VisualElement child0, VisualElement child1, float flexGrow = 1f)
        {
            Row row = CreateRow(child0, flexGrow);
            row.Add(child1);
            return row;
        }
        public Row CreateRowWithName(string name)
        {
            Row row = CreateRow();
            row.name = name;
            return row;
        }
        public Row CreateRowWithName(string name, float flexGrow)
        {
            Row row = CreateRow(flexGrow);
            row.name = name;
            return row;
        }

        public virtual Column CreateColumn()
        {
            return new Column(this);
        }
        public Column CreateColumn(float flexGrow)
        {
            Column column = CreateColumn();
            column.style.flexGrow = flexGrow;
            return column;
        }
        public Column CreateColumn(VisualElement child)
        {
            Column column = CreateColumn();
            column.Add(child);
            return column;
        }
        public Column CreateColumn(VisualElement child, float flexGrow)
        {
            Column column = CreateColumn(flexGrow);
            column.Add(child);
            return column;
        }
        public Column CreateColumnWithName(string name)
        {
            Column column = CreateColumn();
            column.name = name;
            return column;
        }
        public Column CreateColumnWithName(string name, float flexGrow)
        {
            Column column = CreateColumnWithName(name);
            column.style.flexGrow = flexGrow;
            return column;
        }

        public virtual Box CreateBox()
        {
            return new Box(this);
        }
        public Box CreateBox(Color backgroundColor)
        {
            Box box = CreateBox();
            box.style.SetBackgroundColor(backgroundColor);
            return box;
        }

        public virtual SidebarView CreateSidebarView()
        {
            return new SidebarView();
        }
        public SidebarView CreateSidebarView(Action<int> onIndexChangedCallback)
        {
            SidebarView sidebarView = CreateSidebarView();
            sidebarView.onIndexChanged += onIndexChangedCallback;
            return sidebarView;
        }
        public SidebarView CreateSidebarViewWithName(string name)
        {
            SidebarView sidebarView = CreateSidebarView();
            sidebarView.name = name;
            return sidebarView;
        }

        public virtual ToolView CreateToolView()
        {
            return new ToolView();
        }
        public ToolView CreateToolView(float toolBarHeight)
        {
            ToolView toolView = CreateToolView();
            toolView.barHeight = toolBarHeight;
            return toolView;
        }
        public ToolView CreateToolView(float toolBarHeight, Action<int> onIndexChangedCallback)
        {
            ToolView toolView = CreateToolView(toolBarHeight);
            toolView.onIndexChanged += onIndexChangedCallback;
            return toolView;
        }
        public ToolView CreateToolView(Action<int> onIndexChangedCallback)
        {
            ToolView toolView = CreateToolView();
            toolView.onIndexChanged += onIndexChangedCallback;
            return toolView;
        }
        public ToolView CreateToolViewWithName(string name)
        {
            ToolView toolView = CreateToolView();
            toolView.name = name;
            return toolView;
        }

        public virtual VerticalSplitline CreateVerticalSplitline()
        {
            VerticalSplitline verticalSplitline = new VerticalSplitline(this);

            return verticalSplitline;
        }
        public VerticalSplitline CreateVerticalSplitline(float width)
        {
            VerticalSplitline verticalSplitline = CreateVerticalSplitline();
            verticalSplitline.width = width;
            return verticalSplitline;
        }
        public VerticalSplitline CreateVerticalSplitline(Color color, float width = 1f)
        {
            VerticalSplitline verticalSplitline = CreateVerticalSplitline(width);
            verticalSplitline.color = color;
            return verticalSplitline;
        }
        public VerticalSplitline CreateVerticalSplitlineWithName(string name)
        {
            VerticalSplitline verticalSplitline = CreateVerticalSplitline();
            verticalSplitline.name = name;
            return verticalSplitline;
        }
        public VerticalSplitline CreateVerticalSplitlineWithName(string name, float width)
        {
            VerticalSplitline verticalSplitline = CreateVerticalSplitlineWithName(name);
            verticalSplitline.width = width;
            return verticalSplitline;
        }
        public VerticalSplitline CreateVerticalSplitlineWithName(string name, Color color, float width = 1f)
        {
            VerticalSplitline verticalSplitline = CreateVerticalSplitlineWithName(name, width);
            verticalSplitline.color = color;
            return verticalSplitline;
        }

        public virtual HorizontalSplitline CreateHorizontalSplitline()
        {
            return new HorizontalSplitline(this);
        }
        public HorizontalSplitline CreateHorizontalSplitline(float height)
        {
            HorizontalSplitline horizontalSplitline = CreateHorizontalSplitline();
            horizontalSplitline.height = height;
            return horizontalSplitline;
        }
        public HorizontalSplitline CreateHorizontalSplitline(Color color, float height = 1f)
        {
            HorizontalSplitline horizontalSplitline = CreateHorizontalSplitline(height);
            horizontalSplitline.style.color = color;
            return horizontalSplitline;
        }
        public HorizontalSplitline CreateHorizontalSplitlineWithName(string name)
        {
            HorizontalSplitline horizontalSplitline = CreateHorizontalSplitline();
            horizontalSplitline.name = name;
            return horizontalSplitline;
        }
        public HorizontalSplitline CreateHorizontalSplitlineWithName(string name, float height)
        {
            HorizontalSplitline horizontalSplitline = CreateHorizontalSplitlineWithName(name);
            horizontalSplitline.height = height;
            return horizontalSplitline;
        }
        public HorizontalSplitline CreateHorizontalSplitline(string name, Color color, float height = 1f)
        {
            HorizontalSplitline horizontalSplitline = CreateHorizontalSplitlineWithName(name, height);
            horizontalSplitline.color = color;
            return horizontalSplitline;
        }

        public virtual Vector2Field CreateVector2Field()
        {
            Vector2Field vector2Field = new Vector2Field(this);
            CreateAnyValueControlAfter(vector2Field);
            return vector2Field;
        }
        public Vector2Field CreateVector2Field(string label)
        {
            Vector2Field vector2Field = CreateVector2Field();
            vector2Field.label.text = label;
            return vector2Field;
        }
        public Vector2Field CreateVector2Field(string label, Vector2 defaultValue)
        {
            Vector2Field vector2Field = CreateVector2Field(label);
            vector2Field.SetValueWithoutNotify(defaultValue);
            return vector2Field;
        }
        public Vector2Field CreateVector2Field(string label, Action<Vector2> onValueChangedCallback)
        {
            Vector2Field vector2Field = CreateVector2Field(label);
            vector2Field.onValueChanged += onValueChangedCallback;
            return vector2Field;
        }
        public Vector2Field CreateVector2Field(string label, Vector2 defaultValue, Action<Vector2> onValueChangedCallback)
        {
            Vector2Field vector2Field = CreateVector2Field(label, defaultValue);
            vector2Field.onValueChanged += onValueChangedCallback;
            return vector2Field;
        }
        public Vector2Field CreateVector2FieldWithName(string name)
        {
            Vector2Field vector2Field = CreateVector2Field();
            vector2Field.name = name;
            return vector2Field;
        }

        public virtual Vector3Field CreateVector3Field()
        {
            Vector3Field vector3Field = new Vector3Field(this);
            CreateAnyValueControlAfter(vector3Field);
            return vector3Field;
        }
        public Vector3Field CreateVector3Field(string label)
        {
            Vector3Field vector3Field = CreateVector3Field();
            vector3Field.label.text = label;
            return vector3Field;
        }
        public Vector3Field CreateVector3Field(string label, Vector3 defaultValue)
        {
            Vector3Field vector3Field = CreateVector3Field(label);
            vector3Field.SetValueWithoutNotify(defaultValue);
            return vector3Field;
        }
        public Vector3Field CreateVector3Field(string label, Action<Vector3> onValueChangedCallback)
        {
            Vector3Field vector3Field = CreateVector3Field(label);
            vector3Field.onValueChanged += onValueChangedCallback;
            return vector3Field;
        }
        public Vector3Field CreateVector3Field(string label, Vector3 defaultValue, Action<Vector3> onValueChangedCallback)
        {
            Vector3Field vector3Field = CreateVector3Field(label, defaultValue);
            vector3Field.onValueChanged += onValueChangedCallback;
            return vector3Field;
        }
        public Vector3Field CreateVector3FieldWithName(string name)
        {
            Vector3Field vector3Field = CreateVector3Field();
            vector3Field.name = name;
            return vector3Field;
        }

        public virtual Vector4Field CreateVector4Field()
        {
            Vector4Field vector4Field = new Vector4Field(this);
            CreateAnyValueControlAfter(vector4Field);
            return vector4Field;
        }
        public Vector4Field CreateVector4Field(string label)
        {
            Vector4Field vector4Field = CreateVector4Field();
            vector4Field.label.text = label;
            return vector4Field;
        }
        public Vector4Field CreateVector4Field(string label, Vector4 defaultValue)
        {
            Vector4Field vector4Field = CreateVector4Field(label);
            vector4Field.SetValueWithoutNotify(defaultValue);
            return vector4Field;
        }
        public Vector4Field CreateVector4Field(string label, Action<Vector4> onValueChangedCallback)
        {
            Vector4Field vector4Field = CreateVector4Field(label);
            vector4Field.onValueChanged += onValueChangedCallback;
            return vector4Field;
        }
        public Vector4Field CreateVector4Field(string label, Vector4 defaultValue, Action<Vector4> onValueChangedCallback)
        {
            Vector4Field vector4Field = CreateVector4Field(label, defaultValue);
            vector4Field.onValueChanged += onValueChangedCallback;
            return vector4Field;
        }
        public Vector4Field CreateVector4FieldWithName(string name)
        {
            Vector4Field vector4Field = CreateVector4Field();
            vector4Field.name = name;
            return vector4Field;
        }

        public virtual Vector2IntField CreateVector2IntField()
        {
            Vector2IntField vector2IntField = new Vector2IntField(this);
            CreateAnyValueControlAfter(vector2IntField);
            return vector2IntField;
        }
        public Vector2IntField CreateVector2IntField(string label)
        {
            Vector2IntField vector2IntField = CreateVector2IntField();
            vector2IntField.label.text = label;
            return vector2IntField;
        }
        public Vector2IntField CreateVector2IntField(string label, Vector2Int defaultValue)
        {
            Vector2IntField vector2IntField = CreateVector2IntField(label);
            vector2IntField.SetValueWithoutNotify(defaultValue);
            return vector2IntField;
        }
        public Vector2IntField CreateVector2IntField(string label, Vector2Int defaultValue, Action<Vector2Int> onValueChangedCallback)
        {
            Vector2IntField vector2IntField = CreateVector2IntField(label, defaultValue);
            vector2IntField.onValueChanged += onValueChangedCallback;
            return vector2IntField;
        }
        public Vector2IntField CreateVector2IntFieldWithName(string name)
        {
            Vector2IntField vector2IntField = CreateVector2IntField();
            vector2IntField.name = name;
            return vector2IntField;
        }

        public virtual Vector3IntField CreateVector3IntField()
        {
            Vector3IntField vector3IntField = new Vector3IntField(this);
            CreateAnyValueControlAfter(vector3IntField);
            return vector3IntField;
        }
        public Vector3IntField CreateVector3IntField(string label)
        {
            Vector3IntField vector3IntField = CreateVector3IntField();
            vector3IntField.label.text = label;
            return vector3IntField;
        }
        public Vector3IntField CreateVector3IntField(string label, Vector3Int defaultValue)
        {
            Vector3IntField vector3IntField = CreateVector3IntField(label);
            vector3IntField.SetValueWithoutNotify(defaultValue);
            return vector3IntField;
        }
        public Vector3IntField CreateVector3IntField(string label, Vector3Int defaultValue, Action<Vector3Int> onValueChangedCallback)
        {
            Vector3IntField vector3IntField = CreateVector3IntField(label, defaultValue);
            vector3IntField.onValueChanged += onValueChangedCallback;
            return vector3IntField;
        }
        public Vector3IntField CreateVector3IntFieldWithName(string name)
        {
            Vector3IntField vector3IntField = CreateVector3IntField();
            vector3IntField.name = name;
            return vector3IntField;
        }

        public virtual Slider CreateSlider()
        {
            Slider slider = new Slider(this);
            CreateAnyValueControlAfter(slider);
            return slider;
        }
        public Slider CreateSlider(string label)
        {
            Slider slider = CreateSlider();
            slider.label.text = label;
            return slider;
        }
        public Slider CreateSlider(string label, float defaultValue)
        {
            Slider slider = CreateSlider(label);
            slider.SetValueWithoutNotify(defaultValue);
            return slider;
        }
        public Slider CreateSlider(string label, Action<float> onValueChangedCallback)
        {
            Slider slider = CreateSlider(label);
            slider.onValueChanged += onValueChangedCallback;
            return slider;
        }
        public Slider CreateSlider(string label, float defaultValue, Action<float> onValueChangedCallback)
        {
            Slider slider = CreateSlider(label, defaultValue);
            slider.onValueChanged += onValueChangedCallback;
            return slider;
        }
        public Slider CreateSlider(string label, float minValue, float maxValue)
        {
            Slider slider = CreateSlider(label);
            slider.SetRange(minValue, maxValue);
            return slider;
        }
        public Slider CreateSlider(string label, float minValue, float maxValue, Action<float> onValueChangedCallback)
        {
            Slider slider = CreateSlider(label, minValue, maxValue);
            slider.onValueChanged += onValueChangedCallback;
            return slider;
        }
        public Slider CreateSlider(string label, float defaultValue, float minValue, float maxValue)
        {
            Slider slider = CreateSlider(label, minValue, maxValue);
            slider.SetValueWithoutNotify(defaultValue);
            return slider;
        }
        public Slider CreateSlider(string label, float defaultValue, float minValue, float maxValue, Action<float> onValueChangedCallback)
        {
            Slider slider = CreateSlider(label, defaultValue, minValue, maxValue);
            slider.onValueChanged += onValueChangedCallback;
            return slider;
        }
        public Slider CreateSliderWithName(string name)
        {
            Slider slider = CreateSlider();
            slider.name = name;
            return slider;
        }

        public virtual SliderInt CreateSliderInt()
        {
            SliderInt sliderInt = new SliderInt(this);
            CreateAnyValueControlAfter(sliderInt);
            return sliderInt;
        }
        public SliderInt CreateSliderInt(string label)
        {
            SliderInt sliderInt = CreateSliderInt();
            sliderInt.label.text = label;
            return sliderInt;
        }
        public SliderInt CreateSliderInt(string label, int defaultValue)
        {
            SliderInt sliderInt = CreateSliderInt(label);
            sliderInt.SetValueWithoutNotify(defaultValue);
            return sliderInt;
        }
        public SliderInt CreateSliderInt(string label, Action<int> onValueChangedCallback)
        {
            SliderInt sliderInt = CreateSliderInt(label);
            sliderInt.onValueChanged += onValueChangedCallback;
            return sliderInt;
        }
        public SliderInt CreateSliderInt(string label, int defaultValue, Action<int> onValueChangedCallback)
        {
            SliderInt sliderInt = CreateSliderInt(label, defaultValue);
            sliderInt.onValueChanged += onValueChangedCallback;
            return sliderInt;
        }
        public SliderInt CreateSliderInt(string label, int minValue, int maxValue)
        {
            SliderInt sliderInt = CreateSliderInt(label);
            sliderInt.SetRange(minValue, maxValue);
            return sliderInt;
        }
        public SliderInt CreateSliderInt(string label, int minValue, int maxValue, Action<int> onValueChangedCallback)
        {
            SliderInt sliderInt = CreateSliderInt(label, minValue, maxValue);
            sliderInt.onValueChanged += onValueChangedCallback;
            return sliderInt;
        }
        public SliderInt CreateSliderInt(string label, int defaultValue, int minValue, int maxValue)
        {
            SliderInt sliderInt = CreateSliderInt(label, defaultValue);
            sliderInt.SetRange(minValue, maxValue);
            return sliderInt;
        }
        public SliderInt CreateSliderInt(string label, int defaultValue, int minValue, int maxValue, Action<int> onValueChangedCallback)
        {
            SliderInt sliderInt = CreateSliderInt(label, defaultValue, minValue, maxValue);
            sliderInt.onValueChanged += onValueChangedCallback;
            return sliderInt;
        }
        public SliderInt CreateSliderIntWithName(string name)
        {
            SliderInt sliderInt = CreateSliderInt();
            sliderInt.name = name;
            return sliderInt;
        }

        public virtual MinMaxSlider CreateMinMaxSlider()
        {
            MinMaxSlider minMaxSlider = new MinMaxSlider(this);
            CreateAnyValueControlAfter(minMaxSlider);
            return minMaxSlider;
        }
        public MinMaxSlider CreateMinMaxSlider(string label)
        {
            MinMaxSlider minMaxSlider = CreateMinMaxSlider();
            minMaxSlider.label.text = label;
            return minMaxSlider;
        }
        public MinMaxSlider CreateMinMaxSlider(string label, Action<Vector2> onValueChangedCallback)
        {
            MinMaxSlider minMaxSlider = CreateMinMaxSlider(label);
            minMaxSlider.onValueChanged += onValueChangedCallback;
            return minMaxSlider;
        }
        public MinMaxSlider CreateMinMaxSlider(string label, Vector2 value, float minLimit, float maxLimit)
        {
            MinMaxSlider minMaxSlider = CreateMinMaxSlider();
            minMaxSlider.label.text = label;
            minMaxSlider.minLimit = minLimit;
            minMaxSlider.maxLimit = maxLimit;
            minMaxSlider.value = value;
            return minMaxSlider;
        }
        public MinMaxSlider CreateMinMaxSlider(string label, Vector2 value, float minLimit, float maxLimit, Action<Vector2> onValueChangedCallback)
        {
            MinMaxSlider minMaxSlider = CreateMinMaxSlider(label, value, minLimit, maxLimit);
            minMaxSlider.onValueChanged += onValueChangedCallback;
            return minMaxSlider;
        }
        public MinMaxSlider CreateMinMaxSliderWithName(string name)
        {
            MinMaxSlider minMaxSlider = CreateMinMaxSlider();
            minMaxSlider.name = name;
            return minMaxSlider;
        }

        public virtual Label CreateLabel()
        {
            return new Label();
        }
        public Label CreateLabel(float fontSize)
        {
            Label label = CreateLabel();
            label.style.fontSize = fontSize;
            return label;
        }
        public Label CreateLabel(float fontSize, TextAnchor textAnchor)
        {
            Label label = CreateLabel(fontSize);
            label.style.unityTextAlign = textAnchor;
            return label;
        }
        public Label CreateLabel(string labelText)
        {
            Label label = CreateLabel();
            label.text = labelText;
            return label;
        }
        public Label CreateLabel(TextAnchor textAnchor)
        {
            Label label = CreateLabel();
            label.style.unityTextAlign = textAnchor;
            return label;
        }
        public Label CreateLabel(string labelText, TextAnchor textAnchor)
        {
            Label label = CreateLabel(labelText);
            label.style.unityTextAlign = textAnchor;
            return label;
        }
        public Label CreateLabel(string labelText, float fontSize)
        {
            Label label = CreateLabel(labelText);
            label.style.fontSize = fontSize;
            return label;
        }
        public Label CreateLabel(string labelText, float fontSize, TextAnchor textAnchor)
        {
            Label label = CreateLabel(labelText, fontSize);
            label.style.unityTextAlign = textAnchor;
            return label;
        }
        public Label CreateLabelWithName(string name)
        {
            Label label = CreateLabel();
            label.name = name;
            return label;
        }
        public Label CreateLabelWithName(string name, string labelText)
        {
            Label label = CreateLabelWithName(name);
            label.text = labelText;
            return label;
        }

        public virtual Title CreateTitle()
        {
            return new Title();
        }
        public Title CreateTitle(string titleText)
        {
            Title title = CreateTitle();
            title.text = titleText;
            return title;
        }
        public Title CreateTitleWithName(string name)
        {
            Title title = CreateTitle();
            title.name = name;
            return title;
        }

        public virtual ListView<T> CreateListView<T>()
        {
            return new ListView<T>(this);
        }
        public ListView<T> CreateListView<T>(IList<T> data)
        {
            ListView<T> listView = CreateListView<T>();
            listView.SetData(data);
            return listView;
        }
        public ListView<T> CreateListView<T>(Func<T, int, VisualElement> itemDrawFunction)
        {
            ListView<T> listView = CreateListView<T>();
            listView.SetItemDrawFunction(itemDrawFunction);
            return listView;
        }
        public ListView<T> CreateListView<T>(IList<T> data, Func<T, int, VisualElement> itemDrawFunction)
        {
            ListView<T> listView = CreateListView(data);
            listView.SetItemDrawFunction(itemDrawFunction);
            return listView;
        }
        public ListView<T> CreateListViewWithName<T>(string name)
        {
            ListView<T> listView = CreateListView<T>();
            listView.name = name;
            return listView;
        }

        public virtual VerticalScrollView CreateVerticalScrollView()
        {
            return new VerticalScrollView();
        }
        public VerticalScrollView CreateVerticalScrollViewWithName(string name)
        {
            VerticalScrollView verticalScrollView = CreateVerticalScrollView();
            verticalScrollView.name = name;
            return verticalScrollView;
        }

        public virtual ScrollView CreateScrollView()
        {
            return new ScrollView();
        }
        public ScrollView CreateScrollView(ScrollViewMode scrollViewMode)
        {
            ScrollView scrollView = CreateScrollView();
            scrollView.mode = scrollViewMode;
            switch (scrollViewMode)
            {
                case ScrollViewMode.Vertical: scrollView.horizontalScrollerVisibility = ScrollerVisibility.Hidden; break;
                case ScrollViewMode.Horizontal: scrollView.verticalScrollerVisibility = ScrollerVisibility.Hidden; break;
                default: break;
            }
            return scrollView;
        }

        public virtual VerticalSlideView CreateVerticalSlideView()
        {
            return new VerticalSlideView();
        }
        public VerticalSlideView CreateVerticalSlideView(float flexGrow = 1f)
        {
            VerticalSlideView verticalSlideView = CreateVerticalSlideView();
            verticalSlideView.style.flexGrow = flexGrow;
            return verticalSlideView;
        }

        public virtual HorizontalSlideView CreateHorizontalSlideView()
        {
            return new HorizontalSlideView();
        }
        public HorizontalSlideView CreateHorizontalSlideView(float flexGrow = 1f)
        {
            HorizontalSlideView horizontalSlideView = CreateHorizontalSlideView();
            horizontalSlideView.style.flexGrow = flexGrow;
            return horizontalSlideView;
        }

        public virtual HideableContainer CreateHideableContainer()
        {
            return new HideableContainer();
        }
        public HideableContainer CreateHideableContainer(VisualElement item)
        {
            HideableContainer hideableContainer = CreateHideableContainer();
            hideableContainer.Add(item);
            return hideableContainer;
        }
        public HideableContainer CreateHideableContainerWithName(string name)
        {
            HideableContainer hideableContainer = CreateHideableContainer();
            hideableContainer.name = name;
            return hideableContainer;
        }

        public virtual HelpBox CreateHelpBox()
        {
            return new HelpBox(this);
        }
        public HelpBox CreateHelpBox(string message)
        {
            HelpBox helpBox = CreateHelpBox();
            helpBox.message = message;
            return helpBox;
        }
        public HelpBox CreateHelpBox(float fontSize)
        {
            HelpBox helpBox = CreateHelpBox();
            helpBox.fontSize = fontSize;
            return helpBox;
        }
        public HelpBox CreateHelpBox(string message, float fontSize)
        {
            HelpBox helpBox = CreateHelpBox(message);
            helpBox.fontSize = fontSize;
            return helpBox;
        }
        public HelpBox CreateHelpBoxWithName(string name)
        {
            HelpBox helpBox = CreateHelpBox();
            helpBox.name = name;
            return helpBox;
        }

        public virtual ReadonlyText CreateReadonlyText()
        {
            return new ReadonlyText();
        }
        public ReadonlyText CreateReadonlyText(bool enableRichText = false, bool allowNewline = true)
        {
            ReadonlyText readonlyText = CreateReadonlyText();
            readonlyText.enableRichText = enableRichText;
            if (!allowNewline) readonlyText.style.whiteSpace = WhiteSpace.NoWrap;
            return readonlyText;
        }
        public ReadonlyText CreateReadonlyText(string text, bool enableRichText = false, bool allowNewline = true)
        {
            ReadonlyText readonlyText = CreateReadonlyText(enableRichText, allowNewline);
            readonlyText.text = text;
            return readonlyText;
        }
        public ReadonlyText CreateReadonlyTextWithName(string name, bool enableRichText = false, bool allowNewline = true)
        {
            ReadonlyText readonlyText = CreateReadonlyText(enableRichText, allowNewline);
            readonlyText.name = name;
            return readonlyText;
        }

        public virtual Toggle CreateToggle()
        {
            Toggle toggle = new Toggle(this);
            CreateAnyValueControlAfter(toggle);
            return toggle;
        }
        public Toggle CreateToggle(string label)
        {
            Toggle toggle = CreateToggle();
            toggle.label.text = label;
            return toggle;
        }
        public Toggle CreateToggle(string label, bool defaultValue)
        {
            Toggle toggle = CreateToggle(label);
            toggle.SetValueWithoutNotify(defaultValue);
            return toggle;
        }
        public Toggle CreateToggle(string label, bool defaultValue, Action<bool> onValueChangedCallback)
        {
            Toggle toggle = CreateToggle(label, defaultValue);
            toggle.onValueChanged += onValueChangedCallback;
            return toggle;
        }
        public Toggle CreateToggle(bool defaultValue)
        {
            Toggle toggle = CreateToggle();
            toggle.SetValueWithoutNotify(defaultValue);
            return toggle;
        }
        public Toggle CreateToggle(bool defaultValue, Action<bool> onValueChangedCallback)
        {
            Toggle toggle = CreateToggle(defaultValue);
            toggle.onValueChanged += onValueChangedCallback;
            return toggle;
        }
        public Toggle CreateToggleWithName(string name)
        {
            Toggle toggle = CreateToggle();
            toggle.name = name;
            return toggle;
        }

        public virtual TextField CreateTextField()
        {
            TextField textField = new TextField(this);
            CreateAnyValueControlAfter(textField);
            return textField;
        }
        public TextField CreateTextField(string label)
        {
            TextField textField = CreateTextField();
            textField.label.text = label;
            return textField;
        }
        public TextField CreateTextField(string label, string defaultValue)
        {
            TextField textField = CreateTextField(label);
            textField.SetValueWithoutNotify(defaultValue);
            return textField;
        }
        public TextField CreateTextField(string label, Action<string> onValueChangedCallback)
        {
            TextField textField = CreateTextField(label);
            textField.onValueChanged += onValueChangedCallback;
            return textField;
        }
        public TextField CreateTextField(string label, string defaultValue, Action<string> onValueChangedCallback)
        {
            TextField textField = CreateTextField(label, defaultValue);
            textField.onValueChanged += onValueChangedCallback;
            return textField;
        }
        public TextField CreateTextField(Action<string> onValueChangedCallback)
        {
            TextField textField = CreateTextField();
            textField.onValueChanged += onValueChangedCallback;
            return textField;
        }
        public TextField CreateTextFieldWithoutLabel(string defaultValue)
        {
            TextField textField = CreateTextField();
            textField.SetValueWithoutNotify(defaultValue);
            return textField;
        }
        public TextField CreateTextFieldWithoutLabel(string defaultValue, Action<string> onValueChangedCallback)
        {
            TextField textField = CreateTextFieldWithoutLabel(defaultValue);
            textField.onValueChanged += onValueChangedCallback;
            return textField;
        }
        public TextField CreateTextFieldWithName(string name)
        {
            TextField textField = CreateTextField();
            textField.name = name;
            return textField;
        }

        public virtual SearchField CreateSearchField()
        {
            SearchField searchField = new SearchField(this);
            CreateAnyValueControlAfter(searchField);
            return searchField;
        }
        public SearchField CreateSearchField(string label)
        {
            SearchField searchField = CreateSearchField();
            searchField.label.text = label;
            return searchField;
        }
        public SearchField CreateSearchField(string label, Action<string> onValueChangedCallback)
        {
            SearchField textField = CreateSearchField(label);
            textField.onValueChanged += onValueChangedCallback;
            return textField;
        }
        public SearchField CreateSearchField(string label, string defaultValue, Action<string> onValueChangedCallback)
        {
            SearchField searchField = CreateSearchField(label, onValueChangedCallback);
            searchField.SetValueWithoutNotify(defaultValue);
            return searchField;
        }
        public SearchField CreateSearchField(string label, IList<string> choiceList)
        {
            SearchField searchField = CreateSearchField(label);
            searchField.searchList = choiceList;
            return searchField;
        }
        public SearchField CreateSearchField(string label, string defaultValue, IList<string> choiceList)
        {
            SearchField searchField = CreateSearchField(label, choiceList);
            searchField.SetValueWithoutNotify(defaultValue);
            return searchField;
        }
        public SearchField CreateSearchField(string label, IList<string> choiceList, Action<string> onValueChangedCallback)
        {
            SearchField textField = CreateSearchField(label, choiceList);
            textField.onValueChanged += onValueChangedCallback;
            return textField;
        }
        public SearchField CreateSearchField(string label, string defaultValue, IList<string> choiceList, Action<string> onValueChangedCallback)
        {
            SearchField textField = CreateSearchField(label, defaultValue, choiceList);
            textField.onValueChanged += onValueChangedCallback;
            return textField;
        }
        public SearchField CreateSearchFieldWithoutLabel(IList<string> choiceList)
        {
            SearchField searchField = CreateSearchField();
            searchField.searchList = choiceList;
            return searchField;
        }
        public SearchField CreateSearchFieldWithoutLabel(string defaultValue, IList<string> choiceList)
        {
            SearchField searchField = CreateSearchFieldWithoutLabel(choiceList);
            searchField.SetValueWithoutNotify(defaultValue);
            return searchField;
        }
        public SearchField CreateSearchFieldWithoutLabel(string defaultValue, IList<string> choiceList, Action<string> onValueChangedCallback)
        {
            SearchField searchField = CreateSearchFieldWithoutLabel(defaultValue, choiceList);
            searchField.onValueChanged += onValueChangedCallback;
            return searchField;
        }
        public SearchField CreateSearchFieldWithName(string name)
        {
            SearchField searchField = CreateSearchField();
            searchField.name = name;
            return searchField;
        }

        public virtual ObjectField<T> CreateObjectField<T>() where T : UnityEngine.Object
        {
            ObjectField<T> objectField = new ObjectField<T>(this);
            CreateAnyValueControlAfter(objectField);
            return objectField;
        }
        public ObjectField<T> CreateObjectField<T>(string label) where T : UnityEngine.Object
        {
            ObjectField<T> objectField = CreateObjectField<T>();
            objectField.label.text = label;
            return objectField;
        }
        public ObjectField<T> CreateObjectField<T>(string label, T defaultValue) where T : UnityEngine.Object
        {
            ObjectField<T> objectField = CreateObjectField<T>(label);
            objectField.SetValueWithoutNotify(defaultValue);
            return objectField;
        }
        public ObjectField<T> CreateObjectField<T>(string label, Action<T> onValueChangedCallback) where T : UnityEngine.Object
        {
            ObjectField<T> objectField = CreateObjectField<T>(label);
            objectField.onValueChanged += onValueChangedCallback;
            return objectField;
        }
        public ObjectField<T> CreateObjectField<T>(string label, T defaultValue, Action<T> onValueChangedCallback) where T : UnityEngine.Object
        {
            ObjectField<T> objectField = CreateObjectField(label, defaultValue);
            objectField.onValueChanged += onValueChangedCallback;
            return objectField;
        }
        public ObjectField<T> CreateObjectField<T>(T defaultValue) where T : UnityEngine.Object
        {
            ObjectField<T> objectField = CreateObjectField<T>();
            objectField.SetValueWithoutNotify(defaultValue);
            return objectField;
        }
        public ObjectField<T> CreateObjectField<T>(Action<T> onValueChangedCallback) where T : UnityEngine.Object
        {
            ObjectField<T> objectField = CreateObjectField<T>();
            objectField.onValueChanged += onValueChangedCallback;
            return objectField;
        }
        public ObjectField<T> CreateObjectField<T>(T defaultValue, Action<T> onValueChangedCallback) where T : UnityEngine.Object
        {
            ObjectField<T> objectField = CreateObjectField(defaultValue);
            objectField.onValueChanged += onValueChangedCallback;
            return objectField;
        }
        public ObjectField<T> CreateObjectFieldWithName<T>(string name) where T : UnityEngine.Object
        {
            ObjectField<T> objectField = CreateObjectField<T>();
            objectField.name = name;
            return objectField;
        }

        public virtual EnumField<T> CreateEnumField<T>() where T : Enum
        {
            EnumField<T> enumField = new EnumField<T>(this);
            CreateAnyValueControlAfter(enumField);
            return enumField;
        }
        public EnumField<T> CreateEnumField<T>(string label) where T : Enum
        {
            EnumField<T> enumField = CreateEnumField<T>();
            enumField.label.text = label;
            return enumField;
        }
        public EnumField<T> CreateEnumField<T>(string label, T defaultValue) where T : Enum
        {
            EnumField<T> enumField = CreateEnumField<T>(label);
            enumField.SetValueWithoutNotify(defaultValue);
            return enumField;
        }
        public EnumField<T> CreateEnumField<T>(string label, Action<T> onValueChangedCallback) where T : Enum
        {
            EnumField<T> enumField = CreateEnumField<T>(label);
            enumField.onValueChanged += onValueChangedCallback;
            return enumField;
        }
        public EnumField<T> CreateEnumField<T>(string label, IDictionary<T, string> aliasMap, Action<T> onValueChangedCallback) where T : Enum
        {
            EnumField<T> enumField = CreateEnumField(label, onValueChangedCallback);
            enumField.SetAliasMap(aliasMap);
            return enumField;
        }
        public EnumField<T> CreateEnumField<T>(string label, T defaultValue, Action<T> onValueChangedCallback) where T : Enum
        {
            EnumField<T> enumField = CreateEnumField(label, defaultValue);
            enumField.onValueChanged += onValueChangedCallback;
            return enumField;
        }
        public EnumField<T> CreateEnumField<T>(string label, T defaultValue, IDictionary<T, string> aliasMap) where T : Enum
        {
            EnumField<T> enumField = CreateEnumField(label, defaultValue);
            enumField.SetAliasMap(aliasMap);
            return enumField;
        }
        public EnumField<T> CreateEnumField<T>(string label, T defaultValue, IDictionary<T, string> aliasMap, Action<T> onValueChangedCallback) where T : Enum
        {
            EnumField<T> enumField = CreateEnumField(label, defaultValue, aliasMap);
            enumField.onValueChanged += onValueChangedCallback;
            return enumField;
        }
        public EnumField<T> CreateEnumField<T>(string label, T defaultValue, IDictionary<T, string> aliasMap, IList<T> hideFLags) where T : Enum
        {
            EnumField<T> enumField = CreateEnumField(label, defaultValue, aliasMap);
            enumField.SetHideFlag(hideFLags);
            return enumField;
        }
        public EnumField<T> CreateEnumField<T>(string label, T defaultValue, IDictionary<T, string> aliasMap, IList<T> hideFLags, Action<T> onValueChangedCallback) where T : Enum
        {
            EnumField<T> enumField = CreateEnumField(label, defaultValue, aliasMap, hideFLags);
            enumField.onValueChanged += onValueChangedCallback;
            return enumField;
        }
        public EnumField<T> CreateEnumField<T>(T defaultValue) where T : Enum
        {
            EnumField<T> enumField = CreateEnumField<T>();
            enumField.SetValueWithoutNotify(defaultValue);
            return enumField;
        }
        public EnumField<T> CreateEnumField<T>(T defaultValue, Action<T> onValueChangedCallback) where T : Enum
        {
            EnumField<T> enumField = CreateEnumField(defaultValue);
            enumField.onValueChanged += onValueChangedCallback;
            return enumField;
        }
        public EnumField<T> CreateEnumField<T>(T defaultValue, IDictionary<T, string> aliasMap) where T : Enum
        {
            EnumField<T> enumField = CreateEnumField(defaultValue);
            enumField.SetAliasMap(aliasMap);
            return enumField;
        }
        public EnumField<T> CreateEnumField<T>(T defaultValue, IDictionary<T, string> aliasMap, Action<T> onValueChangedCallback) where T : Enum
        {
            EnumField<T> enumField = CreateEnumField(defaultValue, aliasMap);
            enumField.onValueChanged += onValueChangedCallback;
            return enumField;
        }
        public EnumField<T> CreateEnumField<T>(T defaultValue, IDictionary<T, string> aliasMap, IList<T> hideFLags) where T : Enum
        {
            EnumField<T> enumField = CreateEnumField(defaultValue, aliasMap);
            enumField.SetHideFlag(hideFLags);
            return enumField;
        }
        public EnumField<T> CreateEnumField<T>(T defaultValue, IDictionary<T, string> aliasMap, IList<T> hideFLags, Action<T> onValueChangedCallback) where T : Enum
        {
            EnumField<T> enumField = CreateEnumField(defaultValue, aliasMap, hideFLags);
            enumField.onValueChanged += onValueChangedCallback;
            return enumField;
        }
        public EnumField<T> CreateEnumFieldWithName<T>(string name) where T : Enum
        {
            EnumField<T> enumField = CreateEnumField<T>();
            enumField.name = name;
            return enumField;
        }

        public virtual DropdownField CreateDropdownField()
        {
            DropdownField dropdownField = new DropdownField(this);
            CreateAnyValueControlAfter(dropdownField);
            return dropdownField;
        }
        public DropdownField CreateDropdownField(string label)
        {
            DropdownField dropdownField = CreateDropdownField();
            dropdownField.label.text = label;
            return dropdownField;
        }
        public DropdownField CreateDropdownField(string label, string defaultValue)
        {
            DropdownField dropdownField = CreateDropdownField(label);
            dropdownField.SetValueWithoutNotify(defaultValue);
            return dropdownField;
        }
        public DropdownField CreateDropdownField(string label, string defaultValue, Action<string> onValueChangedCallback)
        {
            DropdownField dropdownField = CreateDropdownField(label, defaultValue);
            dropdownField.onValueChanged += onValueChangedCallback;
            return dropdownField;
        }
        public DropdownField CreateDropdownField(string label, IList<string> choiceList)
        {
            DropdownField dropdownField = CreateDropdownField(label);
            dropdownField.choiceList = choiceList;
            return dropdownField;
        }
        public DropdownField CreateDropdownField(string label, IList<string> choiceList, string defaultValue)
        {
            DropdownField dropdownField = CreateDropdownField(label, defaultValue);
            dropdownField.choiceList = choiceList;
            return dropdownField;
        }
        public DropdownField CreateDropdownField(string label, IList<string> choiceList, Action<string> onValueChangedCallback)
        {
            DropdownField dropdownField = CreateDropdownField(label, choiceList);
            dropdownField.onValueChanged += onValueChangedCallback;
            return dropdownField;
        }
        public DropdownField CreateDropdownField(string label, IList<string> choiceList, string defaultValue, Action<string> onValueChangedCallback)
        {
            DropdownField dropdownField = CreateDropdownField(label, choiceList, defaultValue);
            dropdownField.onValueChanged += onValueChangedCallback;
            return dropdownField;
        }
        public DropdownField CreateDropdownField(IList<string> choiceList)
        {
            DropdownField dropdownField = CreateDropdownField();
            dropdownField.choiceList = choiceList;
            return dropdownField;
        }
        public DropdownField CreateDropdownField(IList<string> choiceList, Action<string> onValueChangedCallback)
        {
            DropdownField dropdownField = CreateDropdownField(choiceList);
            dropdownField.onValueChanged += onValueChangedCallback;
            return dropdownField;
        }
        public DropdownField CreateDropdownField(IList<string> choiceList, string defaultValue, Action<string> onValueChangedCallback)
        {
            DropdownField dropdownField = CreateDropdownField(choiceList, onValueChangedCallback);
            dropdownField.SetValueWithoutNotify(defaultValue);
            return dropdownField;
        }
        public DropdownField CreateDropdownField(Action<string> onValueChangedCallback)
        {
            DropdownField dropdownField = CreateDropdownField();
            dropdownField.onValueChanged += onValueChangedCallback;
            return dropdownField;
        }
        public DropdownField CreateDropdownFieldWithoutLabel(string defaultValue)
        {
            DropdownField dropdownField = CreateDropdownField();
            dropdownField.SetValueWithoutNotify(defaultValue);
            return dropdownField;
        }
        public DropdownField CreateDropdownFieldWithoutLabel(string defaultValue, Action<string> onValueChangedCallback)
        {
            DropdownField dropdownField = CreateDropdownFieldWithoutLabel(defaultValue);
            dropdownField.onValueChanged += onValueChangedCallback;
            return dropdownField;
        }
        public DropdownField CreateDropdownFieldWithoutLabel(string defaultValue, IList<string> choiceList, Action<string> onValueChangedCallback)
        {
            DropdownField dropdownField = CreateDropdownFieldWithoutLabel(defaultValue, onValueChangedCallback);
            dropdownField.choiceList = choiceList;
            return dropdownField;
        }
        public DropdownField CreateDropdownFieldWithName(string name)
        {
            DropdownField dropdownField = CreateDropdownField();
            dropdownField.name = name;
            return dropdownField;
        }

        public virtual Button CreateButton()
        {
            return new Button(this);
        }
        public Button CreateButton(string label)
        {
            Button button = CreateButton();
            button.SetLabel(label);
            return button;
        }
        public Button CreateButton(string label, float minHeight)
        {
            Button button = CreateButton(label);
            button.style.SetMinHeight(minHeight);
            return button;
        }
        public Button CreateButton(string label, Action callback)
        {
            Button button = CreateButton(label);
            button.onClick += callback;
            return button;
        }
        public Button CreateButton(string label, Action callback, float minHeight)
        {
            Button button = CreateButton(label, callback);
            button.style.SetMinHeight(minHeight);
            return button;
        }
        public Button CreateButton(Action callback)
        {
            Button button = CreateButton();
            button.onClick += callback;
            return button;
        }
        public Button CreateButton(Action callback, float minHeight)
        {
            Button button = CreateButton(callback);
            button.style.SetMinHeight(minHeight);
            return button;
        }
        public Button CreateButton(Texture texture)
        {
            Button button = CreateButton();
            button.SetTexture(texture);
            return button;
        }
        public Button CreateButton(Texture texture, Color textureColor)
        {
            Button button = CreateButton();
            button.SetTexture(texture, textureColor);
            return button;
        }
        public Button CreateButton(Texture texture, float size)
        {
            Button button = CreateButton();
            button.SetTexture(texture, size);
            return button;
        }
        public Button CreateButton(Texture texture, float size, Color textureColor)
        {
            Button button = CreateButton();
            button.SetTexture(texture, size, textureColor);
            return button;
        }
        public Button CreateButton(Texture texture, Action callback)
        {
            Button button = CreateButton(texture);
            button.onClick += callback;
            return button;
        }
        public Button CreateButton(Texture texture, float size, Action callback)
        {
            Button button = CreateButton(texture, size);
            button.onClick += callback;
            return button;
        }
        public Button CreateButton(Texture texture, float size, Color textureColor, Action callback)
        {
            Button button = CreateButton(texture, size, textureColor);
            button.onClick += callback;
            return button;
        }
        public Button CreateButton(Texture texture, float size, Color textureColor, Action callback, float minHeight)
        {
            Button button = CreateButton(texture, size, textureColor, callback);
            button.style.SetMinHeight(minHeight);
            return button;
        }
        public Button CreateButton(Texture texture, float size, string label, Action callback)
        {
            Button button = CreateButton(texture, size, callback);
            button.SetLabel(label);
            return button;
        }
        public Button CreateButton(Texture texture, float size, string label, Action callback, float minHeight)
        {
            Button button = CreateButton(texture, size, label, callback);
            button.style.SetMinHeight(minHeight);
            return button;
        }
        public Button CreateButton(Texture texture, string label)
        {
            Button button = CreateButton(texture);
            button.SetLabel(label);
            return button;
        }
        public Button CreateButton(Texture texture, string label, Action callback)
        {
            Button button = CreateButton(texture, label);
            button.onClick += callback;
            return button;
        }
        public Button CreateButtonWithName(string name)
        {
            Button button = CreateButton();
            button.name = name;
            return button;
        }
        public Button CreateButtonWithName(string name, Texture texture, int size)
        {
            Button button = CreateButtonWithName(name);
            button.SetTexture(texture, size);
            return button;
        }
        public Button CreateButtonWithName(string name, Texture texture, int size, Action callback)
        {
            Button button = CreateButtonWithName(name, texture, size);
            button.onClick += callback;
            return button;
        }

        public virtual SwitchButton CreateSwitchButton()
        {
            return new SwitchButton(this);
        }
        public SwitchButton CreateSwitchButton(string label)
        {
            SwitchButton switchButton = CreateSwitchButton();
            switchButton.labelText = label;
            return switchButton;
        }
        public SwitchButton CreateSwitchButton(string label, bool on)
        {
            SwitchButton switchButton = CreateSwitchButton(label);
            switchButton.on = on;
            return switchButton;
        }
        public SwitchButton CreateSwitchButton(string label, bool on, Action<bool> callback)
        {
            SwitchButton switchButton = CreateSwitchButton(label, on);
            switchButton.onClick += callback;
            return switchButton;
        }
        public SwitchButton CreateSwitchButton(string label, bool on, Action<bool> callback, float minHeight)
        {
            SwitchButton switchButton = CreateSwitchButton(label, on, callback);
            switchButton.style.SetMinHeight(minHeight);
            return switchButton;
        }
        public SwitchButton CreateSwitchButton(Texture texture, bool on, Action<bool> callback)
        {
            SwitchButton switchButton = CreateSwitchButton();
            switchButton.SetTexture(texture);
            switchButton.onClick += callback;
            switchButton.on = on;
            return switchButton;
        }
        public SwitchButton CreateSwitchButton(Texture texture, float size, bool on, Action<bool> callback)
        {
            SwitchButton switchButton = CreateSwitchButton(texture, on, callback);
            switchButton.SetImageSize(size);
            return switchButton;
        }

        public SwitchButton CreateSwitchButton(Texture texture, string label, bool on, Action<bool> callback)
        {
            SwitchButton switchButton = CreateSwitchButton(label, on, callback);
            switchButton.SetTexture(texture);
            return switchButton;
        }
        public SwitchButton CreateSwitchButton(Texture texture, float size, string label, bool on, Action<bool> callback)
        {
            SwitchButton switchButton = CreateSwitchButton(label, on, callback);
            switchButton.SetTexture(texture, size);
            return switchButton;
        }
        public SwitchButton CreateSwitchButtonWithName(string name)
        {
            SwitchButton switchButton = CreateSwitchButton();
            switchButton.name = name;
            return switchButton;
        }

        public virtual LoadingButton CreateLoadingButton()
        {
            return new LoadingButton(this);
        }
        public LoadingButton CreateLoadingButton(string label)
        {
            LoadingButton loadingButton = CreateLoadingButton();
            loadingButton.labelText = label;
            return loadingButton;
        }
        public LoadingButton CreateLoadingButton(string label, Func<Task> callback)
        {
            LoadingButton loadingButton = CreateLoadingButton(label);
            loadingButton.onClick += callback;
            return loadingButton;
        }
        public LoadingButton CreateLoadingButton(string label, Func<Task> callback, float minHeight)
        {
            LoadingButton loadingButton = CreateLoadingButton(label, callback);
            loadingButton.style.SetMinHeight(minHeight);
            return loadingButton;
        }
        public LoadingButton CreateLoadingButtonWithName(string name)
        {
            LoadingButton switchButton = CreateLoadingButton();
            switchButton.name = name;
            return switchButton;
        }

        public virtual Icon CreateIcon()
        {
            return new Icon();
        }
        public Icon CreateIcon(float size)
        {
            Icon icon = CreateIcon();
            icon.SetSize(size);
            return icon;
        }
        public Icon CreateIcon(Texture texture)
        {
            Icon icon = CreateIcon();
            icon.image = texture;
            return icon;
        }
        public Icon CreateIcon(Texture texture, Color tintColor)
        {
            Icon icon = CreateIcon(texture);
            icon.tintColor = tintColor;
            return icon;
        }
        public Icon CreateIcon(Texture texture, float size)
        {
            return CreateIcon(texture, size, size);
        }
        public Icon CreateIcon(Texture texture, float size, Color tintColor)
        {
            return CreateIcon(texture, size, size, tintColor);
        }
        public Icon CreateIcon(Texture texture, float width, float height)
        {
            Icon icon = CreateIcon(texture);
            icon.SetSize(width, height);
            return icon;
        }
        public Icon CreateIcon(Texture texture, float width, float height, Color tintColor)
        {
            Icon icon = CreateIcon(texture, width, height);
            icon.tintColor = tintColor;
            return icon;
        }
        public Icon CreateIconWithName(string name)
        {
            Icon icon = CreateIcon();
            icon.name = name;
            return icon;
        }
        public Icon CreateIconWithName(string name, Texture texture, float size)
        {
            return CreateIconWithName(name, texture, size, size);
        }
        public Icon CreateIconWithName(string name, Texture texture, float size, Color tintColor)
        {
            Icon icon = CreateIconWithName(name, texture, size);
            icon.tintColor = tintColor;
            return icon;
        }
        public Icon CreateIconWithName(string name, Texture texture, float width, float height)
        {
            Icon icon = CreateIconWithName(name);
            icon.SetSize(width, height);
            icon.image = texture;
            return icon;
        }
        public Icon CreateIconWithName(string name, Texture texture, float width, float height, Color tintColor)
        {
            Icon icon = CreateIconWithName(name, texture, width, height);
            icon.tintColor = tintColor;
            return icon;
        }

        public virtual IntField CreateIntField()
        {
            IntField intField = new IntField(this);
            CreateAnyValueControlAfter(intField);
            return intField;
        }
        public IntField CreateIntField(string label)
        {
            IntField intField = CreateIntField();
            intField.label.text = label;
            return intField;
        }
        public IntField CreateIntField(string label, int defaultValue)
        {
            IntField intField = CreateIntField(label);
            intField.SetValueWithoutNotify(defaultValue);
            return intField;
        }
        public IntField CreateIntField(string label, Action<int> onValueChangedCallback)
        {
            IntField intField = CreateIntField(label);
            intField.onValueChanged += onValueChangedCallback;
            return intField;
        }
        public IntField CreateIntField(string label, int defaultValue, Action<int> onValueChangedCallback)
        {
            IntField intField = CreateIntField(label, defaultValue);
            intField.onValueChanged += onValueChangedCallback;
            return intField;
        }
        public IntField CreateIntField(int defaultValue)
        {
            IntField intField = CreateIntField();
            intField.SetValueWithoutNotify(defaultValue);
            return intField;
        }
        public IntField CreateIntField(int defaultValue, Action<int> onValueChangedCallback)
        {
            IntField intField = CreateIntField(defaultValue);
            intField.onValueChanged += onValueChangedCallback;
            return intField;
        }
        public IntField CreateIntField(Action<int> onValueChangedCallback)
        {
            IntField intField = CreateIntField();
            intField.onValueChanged += onValueChangedCallback;
            return intField;
        }
        public IntField CreateIntFieldWithName(string name)
        {
            IntField intField = CreateIntField();
            intField.name = name;
            return intField;
        }
        public IntField CreateIntFieldWithName(string name, string label)
        {
            IntField intField = CreateIntFieldWithName(name);
            intField.label.text = label;
            return intField;
        }
        public IntField CreateIntFieldWithName(string name, string label, int defaultValue)
        {
            IntField intField = CreateIntFieldWithName(name, label);
            intField.SetValueWithoutNotify(defaultValue);
            return intField;
        }
        public IntField CreateIntFieldWithName(string name, string label, Action<int> onValueChangedCallback)
        {
            IntField intField = CreateIntFieldWithName(name, label);
            intField.onValueChanged += onValueChangedCallback;
            return intField;
        }
        public IntField CreateIntFieldWithName(string name, string label, int defaultValue, Action<int> onValueChangedCallback)
        {
            IntField intField = CreateIntFieldWithName(name, label, defaultValue);
            intField.onValueChanged += onValueChangedCallback;
            return intField;
        }

        public virtual FloatField CreateFloatField()
        {
            FloatField floatField = new FloatField(this);
            CreateAnyValueControlAfter(floatField);
            return floatField;
        }
        public FloatField CreateFloatField(string label)
        {
            FloatField floatField = CreateFloatField();
            floatField.label.text = label;
            return floatField;
        }
        public FloatField CreateFloatField(string label, float defaultValue)
        {
            FloatField floatField = CreateFloatField(label);
            floatField.SetValueWithoutNotify(defaultValue);
            return floatField;
        }
        public FloatField CreateFloatField(string label, Action<float> onValueChangedCallback)
        {
            FloatField floatField = CreateFloatField(label);
            floatField.onValueChanged += onValueChangedCallback;
            return floatField;
        }
        public FloatField CreateFloatField(string label, float defaultValue, Action<float> onValueChangedCallback)
        {
            FloatField floatField = CreateFloatField(label, defaultValue);
            floatField.onValueChanged += onValueChangedCallback;
            return floatField;
        }
        public FloatField CreateFloatField(float defaultValue)
        {
            FloatField floatField = CreateFloatField();
            floatField.SetValueWithoutNotify(defaultValue);
            return floatField;
        }
        public FloatField CreateFloatField(float defaultValue, Action<float> onValueChangedCallback)
        {
            FloatField floatField = CreateFloatField(defaultValue);
            floatField.onValueChanged += onValueChangedCallback;
            return floatField;
        }
        public FloatField CreateFloatField(Action<float> onValueChangedCallback)
        {
            FloatField floatField = CreateFloatField();
            floatField.onValueChanged += onValueChangedCallback;
            return floatField;
        }
        public FloatField CreateFloatFieldWithName(string name)
        {
            FloatField floatField = CreateFloatField();
            floatField.name = name;
            return floatField;
        }

        public virtual ColorField CreateColorField()
        {
            ColorField colorField = new ColorField(this);
            CreateAnyValueControlAfter(colorField);
            return colorField;
        }
        public ColorField CreateColorField(string label)
        {
            ColorField colorField = CreateColorField();
            colorField.label.text = label;
            return colorField;
        }
        public ColorField CreateColorField(string label, Color defaultValue)
        {
            ColorField colorField = CreateColorField(label);
            colorField.SetValueWithoutNotify(defaultValue);
            return colorField;
        }
        public ColorField CreateColorField(string label, Color defaultValue, Action<Color> onValueChangedCallback)
        {
            ColorField colorField = CreateColorField(label, defaultValue);
            colorField.onValueChanged += onValueChangedCallback;
            return colorField;
        }

        public virtual CurveField CreateCurveField()
        {
            CurveField curveField = new CurveField(this);
            CreateAnyValueControlAfter(curveField);
            return curveField;
        }
        public CurveField CreateCurveField(string label)
        {
            CurveField curveField = CreateCurveField();
            curveField.label.text = label;
            return curveField;
        }
        public CurveField CreateCurveField(string label, AnimationCurve defaultValue)
        {
            CurveField curveField = CreateCurveField(label);
            curveField.SetValueWithoutNotify(defaultValue);
            return curveField;
        }
        public CurveField CreateCurveField(string label, AnimationCurve defaultValue, Action<AnimationCurve> onValueChangedCallback)
        {
            CurveField curveField = CreateCurveField(label, defaultValue);
            curveField.onValueChanged += onValueChangedCallback;
            return curveField;
        }
        public CurveField CreateCurveField(string label, AnimationCurve defaultValue, Rect range)
        {
            CurveField curveField = CreateCurveField(label, defaultValue);
            curveField.range = range;
            return curveField;
        }
        public CurveField CreateCurveField(string label, AnimationCurve defaultValue, Rect range, Action<AnimationCurve> onValueChangedCallback)
        {
            CurveField curveField = CreateCurveField(label, defaultValue, range);
            curveField.onValueChanged += onValueChangedCallback;
            return curveField;
        }
        public CurveField CreateCurveFieldWithName(string name)
        {
            CurveField curveField = CreateCurveField();
            curveField.name = name;
            return curveField;
        }

        public virtual Foldout CreateFoldout()
        {
            Foldout foldout = new Foldout(this);
            CreateAnyValueControlAfter(foldout);
            return foldout;
        }
        public Foldout CreateFoldout(string label)
        {
            Foldout foldout = CreateFoldout();
            foldout.label.text = label;
            return foldout;
        }
        public Foldout CreateFoldout(string label, bool defaultValue)
        {
            Foldout foldout = CreateFoldout(label);
            foldout.SetValueWithoutNotify(defaultValue);
            return foldout;
        }
        public Foldout CreateFoldout(string label, bool defaultValue, Action<bool> onValueChangedCallback)
        {
            Foldout foldout = CreateFoldout(label, defaultValue);
            foldout.onValueChanged += onValueChangedCallback;
            return foldout;
        }
        public Foldout CreateFoldout(string label, float contentIndent)
        {
            Foldout foldout = CreateFoldout(label);
            foldout.indent = contentIndent;
            return foldout;
        }
        public Foldout CreateFoldoutWithName(string name)
        {
            Foldout foldout = CreateFoldout();
            foldout.name = name;
            return foldout;
        }

        public virtual RadioButtonGroup<T> CreateRadioButtonGroup<T>()
        {
            RadioButtonGroup<T> radioButtonGroup = new RadioButtonGroup<T>(this);
            CreateAnyValueControlAfter(radioButtonGroup);
            return radioButtonGroup;
        }
        public RadioButtonGroup<T> CreateRadioButtonGroup<T>(string label)
        {
            RadioButtonGroup<T> radioButtonGroup = CreateRadioButtonGroup<T>();
            radioButtonGroup.label.text = label;
            return radioButtonGroup;
        }
        public RadioButtonGroup<T> CreateRadioButtonGroup<T>(string label, Action<T> onValueChangedCallback)
        {
            RadioButtonGroup<T> radioButtonGroup = CreateRadioButtonGroup<T>(label);
            radioButtonGroup.onValueChanged += onValueChangedCallback;
            return radioButtonGroup;
        }
        public RadioButtonGroup<T> CreateRadioButtonGroup<T>(string label, IEnumerable<KeyValuePair<string, T>> choices, Action<T> onValueChangedCallback)
        {
            RadioButtonGroup<T> radioButtonGroup = CreateRadioButtonGroup(label, onValueChangedCallback);
            foreach (var choice in choices) radioButtonGroup.AddChoice(choice.Key, choice.Value);
            return radioButtonGroup;
        }
        public RadioButtonGroup<T> CreateRadioButtonGroup<T>(string label, IEnumerable<KeyValuePair<string, T>> choices, T defaultValue, Action<T> onValueChangedCallback)
        {
            RadioButtonGroup<T> radioButtonGroup = CreateRadioButtonGroup(label, choices, onValueChangedCallback);
            radioButtonGroup.SetValueWithoutNotify(defaultValue);
            return radioButtonGroup;
        }
        public RadioButtonGroup<T> CreateRadioButtonGroupWithName<T>(string name)
        {
            RadioButtonGroup<T> radioButtonGroup = CreateRadioButtonGroup<T>();
            radioButtonGroup.name = name;
            return radioButtonGroup;
        }

        public virtual ToolbarPopupSearchField CreatePopupSearchField()
        {
            ToolbarPopupSearchField toolbarPopupSearchField = new ToolbarPopupSearchField();
            toolbarPopupSearchField.style.flexShrink = 1f;
            return toolbarPopupSearchField;
        }

        protected virtual void CreateAnyValueControlAfter<T>(ValueControl<T> valueControl)
        {
            if (undoSystem == null || valueControl is not IUndoable<T> undoable) return;
            undoable.onValueChange += (oldValue, newValue) => undoSystem.AddCommand(new ValueChangeCommand<T>(undoable, oldValue, newValue));
        }
    }
}